import { Injectable, NotFoundException, BadRequestException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, SelectQueryBuilder, In } from 'typeorm';
import { Announcement, User } from '@app/entities';
import { 
  CreateAnnouncementDto, 
  UpdateAnnouncementDto, 
  QueryAnnouncementsDto, 
  BatchAnnouncementActionDto 
} from '../dto';

@Injectable()
export class AnnouncementsService {
  constructor(
    @InjectRepository(Announcement)
    private readonly announcementRepository: Repository<Announcement>,
    @InjectRepository(User)
    private readonly userRepository: Repository<User>,
  ) {}

  async findAll(query: QueryAnnouncementsDto) {
    const queryBuilder = this.createBaseQuery();
    
    // 搜索条件
    if (query.search) {
      queryBuilder.andWhere(
        '(announcement.title LIKE :search OR announcement.content LIKE :search)',
        { search: `%${query.search}%` }
      );
    }

    // 类型筛选
    if (query.type) {
      queryBuilder.andWhere('announcement.type = :type', { type: query.type });
    }

    // 优先级筛选
    if (query.priority !== undefined) {
      queryBuilder.andWhere('announcement.priority = :priority', { priority: query.priority });
    }

    // 状态筛选
    if (query.status !== undefined) {
      queryBuilder.andWhere('announcement.status = :status', { status: query.status });
    }

    // 置顶筛选
    if (query.isTop !== undefined) {
      queryBuilder.andWhere('announcement.isTop = :isTop', { isTop: query.isTop });
    }

    // 作者筛选
    if (query.authorId) {
      queryBuilder.andWhere('announcement.authorId = :authorId', { authorId: query.authorId });
    }

    // 过期筛选
    if (!query.includeExpired) {
      queryBuilder.andWhere(
        '(announcement.expiredAt IS NULL OR announcement.expiredAt > :now)',
        { now: new Date() }
      );
    }

    // 排序
    const sortBy = query.sortBy || 'createdAt';
    const sortOrder = query.sortOrder || 'DESC';
    
    // 置顶公告优先，然后按优先级排序
    queryBuilder.orderBy('announcement.isTop', 'DESC');
    queryBuilder.addOrderBy('announcement.priority', 'DESC');
    queryBuilder.addOrderBy(`announcement.${sortBy}`, sortOrder);

    // 分页
    const page = query.page || 1;
    const limit = query.limit || 10;
    const skip = (page - 1) * limit;

    queryBuilder.skip(skip).take(limit);

    const [announcements, total] = await queryBuilder.getManyAndCount();

    return {
      announcements: announcements.map(announcement => this.formatAnnouncementResponse(announcement)),
      pagination: {
        page,
        limit,
        total,
        totalPages: Math.ceil(total / limit),
      },
    };
  }

  async findOne(id: number): Promise<Announcement> {
    const announcement = await this.announcementRepository.findOne({
      where: { id },
      relations: ['author'],
    });

    if (!announcement) {
      throw new NotFoundException('公告不存在');
    }

    return announcement;
  }

  async create(createAnnouncementDto: CreateAnnouncementDto, userId?: number): Promise<Announcement> {
    // 如果提供了作者ID，验证作者是否存在
    if (createAnnouncementDto.authorId) {
      const author = await this.userRepository.findOne({
        where: { id: createAnnouncementDto.authorId },
      });

      if (!author) {
        throw new BadRequestException('作者不存在');
      }
    } else if (userId) {
      // 使用当前用户作为作者
      const author = await this.userRepository.findOne({
        where: { id: userId },
      });

      if (author) {
        createAnnouncementDto.authorId = userId;
        createAnnouncementDto.authorName = author.username;
      }
    }

    const announcement = this.announcementRepository.create({
      ...createAnnouncementDto,
      publishedAt: createAnnouncementDto.status === 1 ? new Date() : null,
    });

    return await this.announcementRepository.save(announcement);
  }

  async update(id: number, updateAnnouncementDto: UpdateAnnouncementDto): Promise<Announcement> {
    const announcement = await this.findOne(id);

    // 处理发布状态变化
    if (updateAnnouncementDto.status !== undefined) {
      if (updateAnnouncementDto.status === 1 && announcement.status !== 1) {
        // 从未发布变为发布
        announcement.publishedAt = new Date();
      } else if (updateAnnouncementDto.status !== 1 && announcement.status === 1) {
        // 从发布变为未发布
        announcement.publishedAt = null;
      }
    }

    Object.assign(announcement, updateAnnouncementDto);
    return await this.announcementRepository.save(announcement);
  }

  async remove(id: number): Promise<void> {
    const announcement = await this.findOne(id);
    await this.announcementRepository.remove(announcement);
  }

  async batchAction(batchActionDto: BatchAnnouncementActionDto): Promise<any> {
    const { announcementIds, action } = batchActionDto;
    
    switch (action) {
      case 'publish':
        await this.announcementRepository.update(announcementIds, { 
          status: 1, 
          publishedAt: new Date() 
        });
        break;
      case 'unpublish':
        await this.announcementRepository.update(announcementIds, { 
          status: 0, 
          publishedAt: null 
        });
        break;
      case 'top':
        await this.announcementRepository.update(announcementIds, { isTop: true });
        break;
      case 'untop':
        await this.announcementRepository.update(announcementIds, { isTop: false });
        break;
      case 'delete':
        await this.announcementRepository.delete(announcementIds);
        break;
      case 'changeType':
        if (batchActionDto.targetType) {
          await this.announcementRepository.update(announcementIds, { 
            type: batchActionDto.targetType 
          });
        }
        break;
      default:
        throw new BadRequestException('不支持的操作类型');
    }

    return {
      processed: announcementIds.length,
      action,
    };
  }

  async publish(id: number): Promise<void> {
    await this.announcementRepository.update(id, { 
      status: 1, 
      publishedAt: new Date() 
    });
  }

  async unpublish(id: number): Promise<void> {
    await this.announcementRepository.update(id, { 
      status: 0, 
      publishedAt: null 
    });
  }

  async setTop(id: number): Promise<void> {
    await this.announcementRepository.update(id, { isTop: true });
  }

  async removeTop(id: number): Promise<void> {
    await this.announcementRepository.update(id, { isTop: false });
  }

  async getStatsOverview(): Promise<any> {
    const totalAnnouncements = await this.announcementRepository.count();
    const publishedAnnouncements = await this.announcementRepository.count({ 
      where: { status: 1 } 
    });
    const draftAnnouncements = await this.announcementRepository.count({ 
      where: { status: 0 } 
    });
    const topAnnouncements = await this.announcementRepository.count({ 
      where: { isTop: true } 
    });

    // 过期公告数量
    const expiredAnnouncements = await this.announcementRepository
      .createQueryBuilder('announcement')
      .where('announcement.expiredAt IS NOT NULL')
      .andWhere('announcement.expiredAt < :now', { now: new Date() })
      .getCount();

    // 按类型统计
    const typeStats = await this.announcementRepository
      .createQueryBuilder('announcement')
      .select('announcement.type, COUNT(*) as count')
      .groupBy('announcement.type')
      .getRawMany();

    const announcementsByType = {
      系统: 0,
      活动: 0,
      通知: 0,
    };

    typeStats.forEach(stat => {
      announcementsByType[stat.announcement_type] = parseInt(stat.count);
    });

    // 按优先级统计
    const priorityStats = await this.announcementRepository
      .createQueryBuilder('announcement')
      .select('announcement.priority, COUNT(*) as count')
      .groupBy('announcement.priority')
      .getRawMany();

    const announcementsByPriority = { 1: 0, 2: 0, 3: 0 };
    priorityStats.forEach(stat => {
      announcementsByPriority[stat.announcement_priority] = parseInt(stat.count);
    });

    // 最近公告
    const recentAnnouncements = await this.announcementRepository.find({
      where: { status: 1 },
      order: { createdAt: 'DESC' },
      take: 5,
    });

    // 热门公告（按浏览量）
    const popularAnnouncements = await this.announcementRepository.find({
      where: { status: 1 },
      order: { viewCount: 'DESC' },
      take: 5,
    });

    return {
      totalAnnouncements,
      publishedAnnouncements,
      draftAnnouncements,
      expiredAnnouncements,
      topAnnouncements,
      announcementsByType,
      announcementsByPriority,
      recentAnnouncements: recentAnnouncements.map(a => this.formatAnnouncementResponse(a)),
      popularAnnouncements: popularAnnouncements.map(a => this.formatAnnouncementResponse(a)),
    };
  }

  async incrementViewCount(id: number): Promise<void> {
    await this.announcementRepository.increment({ id }, 'viewCount', 1);
  }

  private createBaseQuery(): SelectQueryBuilder<Announcement> {
    return this.announcementRepository
      .createQueryBuilder('announcement')
      .leftJoinAndSelect('announcement.author', 'author');
  }

  private formatAnnouncementResponse(announcement: Announcement): any {
    return {
      ...announcement,
      isPublished: announcement.isPublished,
      isExpired: announcement.isExpired,
      priorityText: announcement.priorityText,
      typeIcon: announcement.typeIcon,
      statusText: announcement.statusText,
      preview: announcement.preview,
    };
  }
}
